package com.waqu.common.utils.collection;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import com.waqu.common.utils.text.StringTools;

/**
 * @Title ArrayMapUtils.java
 * @Package com.waqu.common.utils.collection
 * @author Administrator
 * @date 2015年5月5日 下午6:31:41
 * @version V1.0
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class ArrayMapTools extends AbstractMapTools {

	public static boolean isEmpty(String[] array) {
		return array == null || array.length == 0;
	}

	public static boolean isNotEmpty(String[] array) {
		return !isEmpty(array);
	}

	public static boolean isEmpty(Collection collection) {
		return null == collection || collection.size() <= 0;
	}

	public static boolean isNotEmpty(Collection collection) {
		return !isEmpty(collection);
	}

	public static boolean moreThan(Map<?, ?> map, int min) {
		return isNotEmpty(map) && map.size() > min;
	}

	public static boolean moreThan(Collection<?> collection, int min) {
		return isNotEmpty(collection) && collection.size() > min;
	}

	public static boolean lessThan(Map<?, ?> map, int max) {
		return isNotEmpty(map) && map.size() < max;
	}

	public static boolean lessThan(Collection<?> collection, int max) {
		return isNotEmpty(collection) && collection.size() < max;
	}

	public static boolean equal(Map<?, ?> map, int size) {
		return isNotEmpty(map) && map.size() == size;
	}

	public static boolean equal(Collection<?> collection, int size) {
		return isNotEmpty(collection) && collection.size() == size;
	}

	public static boolean equal(Object[] args, int size) {
		return isNotEmpty(args) && args.length == size;
	}

	public static boolean allEmpty(Collection... collections) {
		if (null != collections && collections.length > 0) {
			for (Collection coll : collections) {
				if (isNotEmpty(coll))
					return false;
			}
		}
		return true;
	}

	public static boolean allEmpty(Map... maps) {
		if (null != maps && maps.length > 0) {
			for (Map map : maps) {
				if (isNotEmpty(map))
					return false;
			}
		}
		return true;
	}

	public static boolean allNotEmpty(Collection... collections) {
		if (null != collections && collections.length > 0) {
			for (Collection coll : collections) {
				if (isEmpty(coll))
					return false;
			}
			return true;
		}
		return false;
	}

	public static boolean allNotEmpty(Map... maps) {
		if (null != maps && maps.length > 0) {
			for (Map map : maps) {
				if (isEmpty(map))
					return false;
			}
			return true;
		}
		return false;
	}

	/**
	 * 包含为空的Collection，查找到第一个为空Map则返回true
	 * 
	 * @Title containsEmpty
	 * @param maps
	 * @return boolean
	 */
	public static boolean containsEmpty(Collection... collections) {
		if (null != collections && collections.length > 0) {
			for (Collection coll : collections) {
				if (isEmpty(coll))
					return true;
			}
		}
		return false;
	}

	/**
	 * 包含不为空Collection，查找到第一个不为空则返回true
	 * 
	 * @Title containsNotEmpty
	 * @param maps
	 * @return boolean
	 */
	public static boolean containsNotEmpty(Collection... collections) {
		if (null != collections && collections.length > 0) {
			for (Collection coll : collections) {
				if (isNotEmpty(coll))
					return true;
			}
		}
		return false;
	}

	/**
	 * 包含为空的Map，查找到第一个为空Map则返回true
	 * 
	 * @Title containsEmpty
	 * @param maps
	 * @return boolean
	 */
	public static boolean containsEmpty(Map... maps) {
		if (null != maps && maps.length > 0) {
			for (Map map : maps) {
				if (isEmpty(map))
					return true;
			}
		}
		return false;
	}

	/**
	 * 包含不为空Map，查找到第一个不为空则返回true
	 * 
	 * @Title containsNotEmpty
	 * @param maps
	 * @return boolean
	 */
	public static boolean containsNotEmpty(Map... maps) {
		if (null != maps && maps.length > 0) {
			for (Map map : maps) {
				if (isNotEmpty(map))
					return true;
			}
		}
		return false;
	}

	/**
	 * 包含并提取<br/>
	 * 如果该Map中包含指定的key，则将该key对应的内容提出并存入coll中
	 * 
	 * @Title containsExt
	 * @param key
	 * @param map
	 * @param coll
	 * @return Collection
	 */
	public static Collection containsExt(String key, Map<String, ?> map, Collection coll) {
		if (map.containsKey(key)) {
			Object obj = map.get(key);
			if (obj instanceof Collection)
				coll.addAll((Collection) obj);
			else
				coll.add(map.get(key));
		}
		return coll;
	}

	/**
	 * 所有的Map中全都包含该key
	 * 
	 * @Title allContainsKey
	 * @param key
	 * @param maps
	 * @return boolean
	 */
	public static boolean allContainsKey(String key, Map... maps) {
		if (isEmpty(maps))
			return false;
		for (Map m : maps) {
			if (!m.containsKey(key))
				return false;
		}
		return true;
	}

	/**
	 * 其中任何一个Map中包含该key
	 * 
	 * @Title allContainsKey
	 * @param key
	 * @param maps
	 * @return boolean
	 */
	public static boolean containsKey(String key, Map... maps) {
		if (isEmpty(maps))
			return false;
		for (Map m : maps) {
			if (m.containsKey(key))
				return true;
		}
		return false;
	}

	/**
	 * 其中任何一个Map中包含该key
	 * 
	 * @Title allContainsKey
	 * @param key
	 * @param maps
	 * @return boolean
	 */
	public static boolean containsKeys(Map maps, String... keys) {
		if (isEmpty(maps) || isEmpty(keys))
			return false;
		for (String k : keys) {
			if (!maps.containsKey(k))
				return false;
		}
		return true;
	}

	/**
	 * 将集合切分成指定大小的多个集合
	 * 
	 * @Description 如：limit( [1,2,3,4,5,6,7] ,3)，<br/>
	 *              返回结果则是[ [1,2,3] , [4,5,6] , [7] ]
	 * @param t
	 *            需要被切分集合
	 * @param size
	 *            切分后单个集合最大容量
	 * @return List<T>
	 */
	public static <T extends Collection> List<T> limit(T t, int size) {
		List<T> arr = new ArrayList<>();
		if (t.size() <= size) {
			arr.add(t);
			return arr;
		}
		try {
			Class clazz = t.getClass();
			Collection coll = null;
			Set in = new HashSet();
			Object[] os = t.toArray();
			for (int i = 0; i < os.length; i++) {
				in.add(os[i]);
				if (in.size() == size || i == os.length - 1) {
					coll = (Collection) clazz.newInstance();
					coll.addAll(in);
					arr.add((T) coll);
					in.clear();
				}
			}
		} catch (InstantiationException | IllegalAccessException e) {
			return null;
		}
		return arr;
	}

	public static boolean isNotEmptyValues(Map maps, Enum... keys) {
		if (isEmpty(maps) || isEmpty(keys))
			return false;
		for (Enum e : keys) {
			if (!maps.containsKey(e.name()) || null == maps.get(e.name()))
				return false;
		}
		return true;
	}

	/**
	 * 其中任何一个Map中包含该key
	 * 
	 * @Title allContainsKey
	 * @param key
	 * @param maps
	 * @return boolean
	 */
	public static boolean isNotEmptyValues(Map maps, String... keys) {
		if (isEmpty(maps) || isEmpty(keys))
			return false;
		for (String k : keys) {
			if (!maps.containsKey(k) || null == maps.get(k))
				return false;
		}
		return true;
	}

	public static boolean isArray(Object arg0) {
		if (null != arg0) {
			if (arg0 instanceof Collection)
				return true;
			else if (arg0.getClass().isArray())
				return true;
			else
				return false;
		}
		return false;
	}

	public static List getArray(Object arg0) {
		return getArray(arg0, null);
	}

	public static List getArray(Object arg0, List array) {
		if (null != arg0 && isArray(arg0)) {
			if (isEmpty(array))
				array = new ArrayList<>();
			if (arg0 instanceof Collection) {
				List list = (List) arg0;
				array.addAll(list);
				return array;
			} else if (arg0.getClass().isArray()) {
				for (int i = 0; i < Array.getLength(arg0); i++) {
					array.add(Array.get(arg0, i));
				}
				return array;
			}
		}
		return null;
	}

	public static <E> E get(E[] args, int index) {
		if (isEmpty(args))
			return null;
		return args.length >= index ? args[index] : null;
	}

	public static <E> E getNullMax(E[] args, int index) {
		if (isEmpty(args))
			return null;
		return args.length >= index ? args[index] : args[args.length - 1];
	}

	public static <E> E getNullMin(E[] args, int index) {
		if (isEmpty(args))
			return null;
		return args.length >= index ? args[index] : args[0];
	}

	public static String getString(Map<String, Object> map, String key) {
		if (isEmpty(map))
			return null;
		return StringTools.toString(map.get(key));
	}

	public static String getString(Map<String, Object> map, Enum key) {
		if (isEmpty(map))
			return null;
		return StringTools.toString(map.get(key.name()));
	}

	public static String getString(Map<String, Object> map, String key, String defaultValue) {
		if (isEmpty(map))
			return defaultValue;
		return StringTools.ternary(map.get(key), defaultValue);
	}

	public static String getString(Map<String, Object> map, Enum key, String defaultValue) {
		if (isEmpty(map))
			return defaultValue;
		return StringTools.ternary(map.get(key.name()), defaultValue);
	}

	public static boolean containsAll(Properties properties, String... keys) {
		for (String k : keys) {
			if (!properties.containsKey(k) || StringTools.isEmpty(properties.getProperty(k))) {
				return false;
			}
		}
		return true;
	}
	
	public static boolean contains(Properties properties, String... keys) {
		for (String k : keys) {
			if (properties.containsKey(k) && StringTools.isNotEmpty(properties.getProperty(k))) {
				return true;
			}
		}
		return false;
	}
	
	/** 数组中某个元素包含在集合中则返回true */
	public static boolean contains(List<String> args, String... arg) {
		for (String ar : arg) {
			if (args.contains(ar)) {
				return true;
			}
		}
		return false;
	}
	
	/** 集合二中某个元素包含在集合一中则返回true, 这个方法还无法提交到git */
	public static boolean contains(List<String> args, List<String> arg) {
		for (String ar : arg) {
			if (args.contains(ar)) {
				return true;
			}
		}
		return false;
	}
	
	public static Object ternary(List<?> objs) {
		return isEmpty(objs) ? null : objs;
	}

	public static Object ternary(List<?> objs, Object defaultValue) {
		return isEmpty(objs) ? defaultValue : objs;
	}

	public static String[] replaceEmpty(String[] args, String defaultValue) {
		if (isEmpty(args))
			return new String[] { defaultValue };
		for (int i = args.length - 1; i >= 0; i--) {
			args[i] = StringTools.isNotEmpty(args[i]) ? args[i] : defaultValue;
		}
		return args;
	}

}
